package com.baidu.calculatordemo

import android.os.Bundle
import android.util.Log
import android.view.View
import android.widget.TextView
import androidx.activity.enableEdgeToEdge
import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import java.util.Stack

class MainActivity : AppCompatActivity() {
    private lateinit var result: TextView
    private lateinit var details: TextView
    //保存所有的算式
    private val processBuilder = StringBuilder()
    //以栈的形式 保存所有的运算数
    private val numStack: Stack<Double> = Stack()
    //以栈的形式 保存所有的运算符
    private val operationStack: Stack<String> = Stack()
    //保存运算符的优先级
    private val operationMap: Map<String, Int> = mapOf(
        "+" to 1,
        "-" to 1,
        "×" to 2,
        "÷" to 2
    )

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        enableEdgeToEdge()
        setContentView(R.layout.activity_main)
        ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main)) { v, insets ->
            val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars())
            v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom)
            insets
        }

        //解析xml中的控件
        result = findViewById(R.id.tv_result)
        details = findViewById(R.id.tv_process)

        initClickListener()
    }

    //点击清除
    fun clear(v: View){
        processBuilder.clear()
        details.text = "0"
        result.text = "0"
    }

    //点击数字
    fun clickNumber(v: View){
        //将View类型的对象 强制转化为对应的类型 TextView
        val numStr = (v as TextView).text.toString()
        //将这个数字拼接到processBuilder中
        val hasAppend = processBuilder.checkIfNeedAppendNum(numStr)
        if (hasAppend) calculate()
        //显示到界面中
        details.text = processBuilder.toString()
    }

    //点击运算符
    //UnicodeTextView : TextView  : View
    fun clickOperator(v: View) {
        val operator = v.tag as String
        //判断末尾是不是有运算符
        val hasChange = processBuilder.checkIfNeedReplaceLastOperator(operator)
        //if (hasChange) calculate()

        //显示到界面中
        details.text = processBuilder.toString()
    }

    //点击等号
    fun clickEqual(v: View) {
        //清空
        details.text = result.text
    }
    //回退
    fun clickBack(v: View){
        if (processBuilder.isNotEmpty()) {
            processBuilder.deleteCharAt(processBuilder.length - 1)
            calculate()
        }

        if (processBuilder.isEmpty()){
            details.text = "0"
        }else{
            details.text = processBuilder.toString()
        }
    }

    //运算
    private fun calculate(){ //78+2
        /**
         * 解析字符串，数字-> 拼接
         * 运算符 -> 将运算数入栈
         *          从当前运算符栈顶去看 这个运算符是不是优先或者和我相同,先运算，将结果和当前运算符都入栈
         */
        var numBuilder = StringBuilder()
        processBuilder.toString().forEachIndexed { i, c ->

            if (c in '0'..'9') { //如果是数字
                numBuilder.append(c)
            }else{
                //是运算符
                //将当前的数字入栈
                numStack.push(numBuilder.toString().toDouble())

                //从运算符栈中 依次取出栈顶的运算符 判断优先级
                val cstr = c.toString()
                while (true){
                    //如果栈为空 结束
                    if (operationStack.isEmpty()) {
                        operationStack.push(cstr)
                        break
                    }
                    //获取栈顶的运算符
                    val operator = operationStack.peek()
                    //如果栈顶运算符的优先级比我当前这个的优先级大或者相同 就去运算 否则 结束
                    if (operationMap[cstr]!! <= operationMap[operator]!!){
                        val num2 = numStack.pop()
                        val num1 = numStack.pop()
                        //运算
                        performCalculate(num1,num2, operator)
                        //运算符出栈
                        operationStack.pop()
                    }else{
                        //当前运算符入栈
                        operationStack.push(cstr)
                        break
                    }
                }

                numBuilder.clear()
            }
        }

        //将最后一个数字入栈
        if (numBuilder.isNotEmpty()){
            numStack.push(numBuilder.toString().toDouble())
        }
        //获取最后的结果
        //先判断运算数栈和运算符栈元素个数 正常运算是 运算数栈比运算符栈元素多一个
        if (numStack.size == operationStack.size){
            //把运算符栈顶的运算符丢弃
            operationStack.pop()
        }

        //
        while (operationStack.isNotEmpty()){
            val num2 = numStack.pop()
            val num1 = numStack.pop()
            val operation = operationStack.pop()
            performCalculate(num1,num2,operation)
        }

        result.text = numStack.pop().toString()

        //78
        //78+
        //78+2
        numStack.clear()
        operationStack.clear()
    }

    private fun performCalculate(num1:Double, num2: Double, operator: String){
        when(operator){
            resources.getString(R.string.add_tag) -> numStack.push(num1 + num2)
            resources.getString(R.string.minus_tag) -> numStack.push(num1 - num2)
            resources.getString(R.string.multiply_tag) -> numStack.push(num1 * num2)
            resources.getString(R.string.divide_tag) -> numStack.push(num1 / num2)
        }
    }

    fun initClickListener(){
        findViewById<TextView>(R.id.tv_clear).setOnClickListener { clear(it) }
        findViewById<TextView>(R.id.tv_delete).setOnClickListener { clickBack(it) }
        findViewById<TextView>(R.id.tv_equal).setOnClickListener { clickEqual(it) }
        findViewById<TextView>(R.id.tv_num0).setOnClickListener { clickNumber(it) }
        findViewById<TextView>(R.id.tv_num1).setOnClickListener { clickNumber(it) }
        findViewById<TextView>(R.id.tv_num2).setOnClickListener { clickNumber(it) }
        findViewById<TextView>(R.id.tv_num3).setOnClickListener { clickNumber(it) }
        findViewById<TextView>(R.id.tv_num4).setOnClickListener { clickNumber(it) }
        findViewById<TextView>(R.id.tv_num5).setOnClickListener { clickNumber(it) }
        findViewById<TextView>(R.id.tv_num6).setOnClickListener { clickNumber(it) }
        findViewById<TextView>(R.id.tv_num7).setOnClickListener { clickNumber(it) }
        findViewById<TextView>(R.id.tv_num8).setOnClickListener { clickNumber(it) }
        findViewById<TextView>(R.id.tv_num9).setOnClickListener { clickNumber(it) }
        findViewById<TextView>(R.id.tv_num00).setOnClickListener { clickNumber(it) }
        findViewById<TextView>(R.id.tv_plus).setOnClickListener { clickOperator(it) }
        findViewById<TextView>(R.id.tv_minus).setOnClickListener { clickOperator(it) }
        findViewById<TextView>(R.id.tv_mutiply).setOnClickListener { clickOperator(it) }
        findViewById<TextView>(R.id.tv_divide).setOnClickListener { clickOperator(it) }
    }
}